{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Farm Planning\n",
    "\n",
    "## Objective and Prerequisites\n",
    "\n",
    "Cultivate your modeling skills with this example, where you’ll learn how to solve a complex, multi-period production planning problem that involves optimizing the operations of a farm over five years.\n",
    "\n",
    "More information on this type of model can be found in example #8 of the fifth edition of Model Building in Mathematical Programming by H. Paul Williams on pages 262 – 263 and 312 – 315.\n",
    "\n",
    "This modeling example is at the advanced level, where we assume that you know Python and the Gurobi Python API and that you have advanced knowledge of building mathematical optimization models. Typically, the objective function and/or constraints of these examples are complex or require advanced features of the Gurobi Python API.\n",
    "\n",
    "**Download the Repository** <br /> You can download the repository containing this and other examples by clicking [here](https://github.com/Gurobi/modeling-examples/archive/master.zip). \n",
    "\n",
    "---\n",
    "## Problem Description\n",
    "\n",
    "A farmer with a 200-acre farm wishes to create a five-year production plan.\n",
    "\n",
    "Currently, he has a herd of 120 cows comprising 20 heifers (young female cows) and 100 adult dairy cows. Each heifer requires 2/3 of an acre to support it and each dairy cow requires one acre.\n",
    "\n",
    "On average, a dairy cow produces 1.1 calves per year. Half of these calves will be bullocks that are sold shortly after birth for an average of $\\$30$ each. The remaining calves, heifers, can either be sold for $\\$40$ or raised until age two when they will become dairy cows. For the current year, all heifers identified for sale have already been sold.\n",
    "\n",
    "The general practice is to sell all dairy cows at the age of 12 for an average of $\\$120$ each. However, each year an average of $5\\%$ of heifers and $2\\%$ of dairy cows die. At present, the farmer’s herd of 120 cows is evenly distributed with 10 cows per age from newborn to 11 years old.\n",
    "\n",
    "The milk from a dairy cow can be sold for $\\$370$ annually. The farmer can currently house up to 130 cows, but this capacity limit can be increased for $\\$200$ per additional cow.\n",
    "\n",
    "Each dairy cow requires 0.6 tons of grain and 0.7 tons of sugar beet per year. Both of these can be grown on the farm. Each acre can yield 1.5 tons of sugar beet. However, only 80 acres are suitable for growing grain, and those acres have different levels of productivity as follows:\n",
    "\n",
    "| Land Group | Area (Acres) | Grain Production (Tons/Acre) |\n",
    "| --- | --- | --- |\n",
    "| Group 1 | 20 | 1.10 |\n",
    "| Group 2 | 30 | 0.90 |\n",
    "| Group 3 | 20 | 0.80 |\n",
    "| Group 4 | 10 | 0.65 |\n",
    "\n",
    "Sugar beet can be bought for $\\$70$ a ton and sold for $\\$58$ a ton. Grain can be bought for $\\$90$ a ton and sold for $\\$75$ a ton.\n",
    "\n",
    "The annual labor requirements for cows as well as grain and sugar beet production are as follows:\n",
    "\n",
    "| <i></i> | Labor Required (Hr/Year) |\n",
    "| --- | --- |\n",
    "| Heifer | 10 |\n",
    "| Milk-producing Cow | 42 |\n",
    "| Acre Devoted to Grain | 4 |\n",
    "| Acre Devoted to Sugar Beet| 14 |\n",
    "\n",
    "Other annual costs are as follows:\n",
    "\n",
    "| <i></i> | Cost (USD/Year) |\n",
    "| --- | --- |\n",
    "| Heifer | 50 |\n",
    "| Milk-producing Cow | 100 |\n",
    "| Acre Devoted to Grain | 15 |\n",
    "| Acre Devoted to Sugar Beet| 10 |\n",
    "\n",
    "Labor currently costs the farmer $\\$4000$ per year and that cost provides 5,500 hours of labor. Additional labor can be paid for at the rate of $\\$1.20$ per hour.\n",
    "\n",
    "Any capital expenditure can be financed with a 10-year loan at $15\\%$ interest annually. The interest and principal are paid back in 10 equal annual payments. It is prohibited for the annual cash flow to be negative.\n",
    "\n",
    "The farmer does not want to reduce the total number of dairy cows at the end of the five-year period by more than $50\\%$, nor does he want to increase their number by more than $75\\%$.\n",
    "\n",
    "What plan should the farmer follow over the next five years in order to maximize profit?\n",
    "\n",
    "---\n",
    "## Model Formulation\n",
    "\n",
    "### Sets and Indices\n",
    "\n",
    "$t \\in \\text{Years}=\\{1,2,\\dots,5\\}$: Set of years.\n",
    "\n",
    "$l \\in \\text{Lands}=\\{1,2,3,4\\}$: Set of land groups.\n",
    "\n",
    "$k \\in \\text{Ages}=\\{1,2,\\dots,12\\}$: Set of cow ages.\n",
    "\n",
    "### Parameters\n",
    "\n",
    "$\\text{Installment} \\in \\mathbb{R}^+$: Annual payment for each $\\$200$ loan. It can be computed as follows.\n",
    "\n",
    "$$\n",
    "\\text{Installment}= \\text{Loan}*r*\\frac{(1+r)^n}{(1+r)^n-1},\n",
    "$$\n",
    "\n",
    "where $\\text{Loan}$ is the loan amount of $\\$200$, $r$ is the interest rate of $15\\%$, and $n$ represents the ten-year period. Note that the book reports a value of $\\$39.71$ instead of $\\$39.85$.\n",
    "\n",
    "$\\text{Housing_cap} \\in \\mathbb{N}$: Number of cows that can be housed.\n",
    "\n",
    "$\\text{Land_cap} \\in \\mathbb{R}^+$: Land available (in Acres).\n",
    "\n",
    "$\\text{Labor_cap} \\in \\mathbb{R}^+$: Regular labor available (in hours) in a year.\n",
    "\n",
    "$\\text{GR_intake} \\in \\mathbb{R}^+$: Tons of grain consumed by a dairy cow in a year.\n",
    "\n",
    "$\\text{SB_intake} \\in \\mathbb{R}^+$: Tons of sugar beet consumed by a dairy cow in a year.\n",
    "\n",
    "$\\text{HF_land} \\in \\mathbb{R}^+$: Acres required for sustaining each heifer.\n",
    "\n",
    "$\\text{HF_labor} \\in \\mathbb{R}^+$: Hours of labor required in a year by each heifer.\n",
    "\n",
    "$\\text{Cow_labor} \\in \\mathbb{R}^+$: Hours of labor required in a year by each dairy cow.\n",
    "\n",
    "$\\text{GR_labor} \\in \\mathbb{R}^+$: Hours of labor required in a year by each acre of land devoted to grains.\n",
    "\n",
    "$\\text{SB_labor} \\in \\mathbb{R}^+$: Hours of labor required in a year by each acre of land devoted to sugar beet.\n",
    "\n",
    "$\\text{HF_decay} \\in [0,1] \\subset \\mathbb{R}^+$: Average proportion of heifers that die in a year.\n",
    "\n",
    "$\\text{Cow_decay} \\in [0,1] \\subset \\mathbb{R}^+$: Average proportion of dairy cows that die in a year.\n",
    "\n",
    "$\\text{Birthrate} \\in \\mathbb{R}^+$: Expected number of calves produced by a dairy cow in a year.\n",
    "\n",
    "$\\text{Min_final_cows} \\in \\mathbb{N}$: Minimum number of dairy cows at the end of the planning horizon.\n",
    "\n",
    "$\\text{Max_final_cows} \\in \\mathbb{N}$: Maximum number of dairy cows at the end of the planning horizon.\n",
    "\n",
    "$\\text{Initial_HF} \\in \\mathbb{R}^+$: Number of heifers of each age at the beginning of the planning horizon.\n",
    "\n",
    "$\\text{Initial_cows} \\in \\mathbb{R}^+$: Number of dairy cows of each age at the beginning of the planning horizon.\n",
    "\n",
    "$\\text{BL_price} \\in \\mathbb{R}^+$: Price for selling one bullock.\n",
    "\n",
    "$\\text{HF_price} \\in \\mathbb{R}^+$: Price for selling one heifer.\n",
    "\n",
    "$\\text{Cow_price} \\in \\mathbb{R}^+$: Price for selling one dairy cow.\n",
    "\n",
    "$\\text{Milk_price} \\in \\mathbb{R}^+$: Price for selling the milk produced by a dairy cow in a year.\n",
    "\n",
    "$\\text{GR_price} \\in \\mathbb{R}^+$: Price for selling a ton of grain.\n",
    "\n",
    "$\\text{SB_price} \\in \\mathbb{R}^+$: Price for selling a ton of sugar beet.\n",
    "\n",
    "$\\text{GR_cost} \\in \\mathbb{R}^+$: Cost for purchasing a ton of grain.\n",
    "\n",
    "$\\text{SB_cost} \\in \\mathbb{R}^+$: Cost for purchasing a ton of sugar beet.\n",
    "\n",
    "$\\text{Overtime_cost} \\in \\mathbb{R}^+$: Cost for getting an hour of overtime.\n",
    "\n",
    "$\\text{Regular_time_cost} \\in \\mathbb{R}^+$: Cost for having 5,500 hours of labor in regular time.\n",
    "\n",
    "$\\text{HF_cost} \\in \\mathbb{R}^+$: Yearly cost for supporting a heifer.\n",
    "\n",
    "$\\text{Cow_cost} \\in \\mathbb{R}^+$: Yearly cost for supporting a dairy cow.\n",
    "\n",
    "$\\text{GR_land_cost} \\in \\mathbb{R}^+$: Yearly cost for supporting an acre of land devoted to grain.\n",
    "\n",
    "$\\text{SB_land_cost} \\in \\mathbb{R}^+$: Yearly cost for supporting an acre of land devoted to sugar beet.\n",
    "\n",
    "$\\text{SB_yield} \\in \\mathbb{R}^+$: Sugar beet yield.\n",
    "\n",
    "$\\text{GR_yield}_l \\in \\mathbb{R}^+$: Grain yield at land group $l$.\n",
    "\n",
    "$\\text{GR_area}_l \\in \\mathbb{R}^+$: Number of acres suitable for growing grain in land group $l$.\n",
    "\n",
    "### Decision Variables\n",
    "\n",
    "$\\text{Outlay}_t \\in \\mathbb{R}^+$: Amount of money (in units of $\\$200$) spent on renting houses in year $t$.\n",
    "\n",
    "$\\text{Overtime}_t \\in \\mathbb{R}^+$: Number of extra labor hours needed in year $t$.\n",
    "\n",
    "$\\text{Newborn}_t \\in \\mathbb{R}^+$: Number of newborn heifers left in year $t$ to be raised.\n",
    "\n",
    "$\\text{HF_sell}_t \\in \\mathbb{R}^+$: Number of newborn heifers to sell in year $t$.\n",
    "\n",
    "$\\text{Profit}_t \\in \\mathbb{R}^+$: Profit attained in year $t$.\n",
    "\n",
    "$\\text{SB_buy}_t \\in \\mathbb{R}^+$: Number of tons of sugar beet to buy in year $t$.\n",
    "\n",
    "$\\text{SB_sell}_t \\in \\mathbb{R}^+$: Number of tons of sugar beet to sell in year $t$.\n",
    "\n",
    "$\\text{GR_buy}_t \\in \\mathbb{R}^+$: Number of tons of grain to buy in year $t$.\n",
    "\n",
    "$\\text{GR_sell}_t \\in \\mathbb{R}^+$: Number of tons of grain to sell in year $t$.\n",
    "\n",
    "$\\text{SB}_t \\in \\mathbb{R}^+$: Number of tons of sugar beet to grow in year $t$.\n",
    "\n",
    "$\\text{GR}_{t,l} \\in \\mathbb{R}^+$: Number of tons of grain to grow in year $t$ at land group $l$.\n",
    "\n",
    "$\\text{Cows}_{t,k} \\in \\mathbb{R}^+$: Number of cows of age $k$ available in year $t$.\n",
    "\n",
    "\n",
    "### Objective Function\n",
    "\n",
    "- **Profit**: Maximize the total profit (in USD) of the planning horizon. Notice that, to make capital expenditure as costly in latter years as in former ones, it is necessary to subtract pending loan payments.\n",
    "\n",
    "\\begin{equation}\n",
    "\\text{Maximize} \\quad Z = \\sum_{t \\in \\text{Years}}{\\text{Profit}_t - installment*(t+4)*\\text{Outlay}_t}\n",
    "\\end{equation}\n",
    "\n",
    "### Constraints\n",
    "\n",
    "- **Housing Capacity**: Livestock cannot exceed the installed capacity plus house rental in year $t$.\n",
    "\n",
    "\\begin{equation}\n",
    "\\text{Newborn}_t + \\sum_{k \\in \\text{Ages} \\setminus \\{12\\}}{\\text{Cows}_{t,k}} \\leq \\text{Housing_cap} + \\sum_{d \\in \\text{Years}: d \\leq t}{\\text{Outlay}_d} \\quad \\forall t \\in \\text{Years}\n",
    "\\end{equation}\n",
    "\n",
    "- **Food Consumption**: There must be enough food to feed the livestock in year $t$.\n",
    "\n",
    "- Grain.\n",
    "\n",
    "\\begin{equation}\n",
    "\\sum_{k \\in \\text{Ages} \\setminus \\{1,12\\}}{\\text{GR_intake}*\\text{Cows}_{t,k}} \\leq \\text{GR_buy}_t - \\text{GR_sell}_t + \\sum_{l \\in \\text{Lands}}{\\text{GR}_{t,l}} \\quad \\forall t \\in \\text{Years}\n",
    "\\end{equation}\n",
    "\n",
    "- Sugar beet.\n",
    "\n",
    "\\begin{equation}\n",
    "\\sum_{k \\in \\text{Ages} \\setminus \\{1,12\\}}{\\text{SB_intake}*\\text{Cows}_{t,k}} \\leq \\text{SB_buy}_t - \\text{SB_sell}_t + \\text{SB}_t \\quad \\forall t \\in \\text{Years}\n",
    "\\end{equation}\n",
    "\n",
    "- **Grain Growing**: Grain produced on land $l$ cannot exceed the production capacity of year $t$.\n",
    "\n",
    "\\begin{equation}\n",
    "\\text{GR}_{t,l} \\leq \\text{GR_yield}_l*\\text{GR_area}_l \\quad \\forall (t,l) \\in \\text{Years} \\times \\text{Lands}\n",
    "\\end{equation}\n",
    "\n",
    "- **Land Capacity**: Use of space in year $t$ cannot exceed available land.\n",
    "\n",
    "\\begin{equation}\n",
    "\\frac{1}{\\text{SB_yield}}*\\text{SB}_t + \\text{HF_land}*(\\text{Newborn}_t + \\text{Cow}_{t,1}) + \n",
    "\\end{equation}\n",
    "\n",
    "\\begin{equation}\n",
    "\\sum_{k \\in \\text{Ages} \\setminus \\{1,12\\}}{\\text{Cows}_{t,k}} + \n",
    "\\end{equation}\n",
    "\n",
    "\\begin{equation}\n",
    "\\sum_{l \\in \\text{Lands}}{\\frac{\\text{GR}_{t,l}}{\\text{GR_yield}_l}} \\leq \\text{Land_cap} \\quad \\forall t \\in \\text{Years}\n",
    "\\end{equation}\n",
    "\n",
    "- **Labor**: Labor required to run the farm in year $t$ cannot exceed contracted time plus overtime.\n",
    "\n",
    "\\begin{equation}\n",
    "\\text{HF_labor}*(\\text{Newborn}_t + \\text{Cow}_{t,1}) + \n",
    "\\end{equation}\n",
    "\n",
    "\\begin{equation}\n",
    "\\sum_{k \\in \\text{Ages} \\setminus \\{1,12\\}}{\\text{Cow_labor}*\\text{Cow}_{t,k}} + \n",
    "\\end{equation}\n",
    "\n",
    "\\begin{equation}\n",
    "\\sum_{l \\in \\text{Lands}}{\\frac{\\text{GR_labor}*\\text{GR}_{t,l}}{\\text{GR_yield}_l}} + \n",
    "\\end{equation}\n",
    "\n",
    "\\begin{equation}\n",
    "\\frac{\\text{SB_labor}*\\text{SB}_t}{\\text{SB_yield}} \\leq \\text{Labor_cap} + \\text{Overtime}_t \\qquad \\forall t \\in \\text{Years}\n",
    "\\end{equation}\n",
    "\n",
    "\n",
    "- **Continuity**: Livestock in year $t$ have to survive the previous year.\n",
    "\n",
    "\\begin{equation}\n",
    "\\text{Cows}_{t,1} = (1-\\text{HF_decay})*\\text{Newborn}_{t-1} \\quad \\forall t \\in \\text{Years} \\setminus \\{1\\}\n",
    "\\end{equation}\n",
    "\n",
    "\\begin{equation}\n",
    "\\text{Cows}_{t,2} = (1-\\text{HF_decay})*\\text{Cows}_{t-1,1} \\quad \\forall t \\in \\text{Years} \\setminus \\{1\\}\n",
    "\\end{equation}\n",
    "\n",
    "\\begin{equation}\n",
    "\\text{Cows}_{t,k+1} = (1-\\text{Cow_decay})*\\text{Cows}_{t-1,k} \\quad \\forall (t,k) \\in \\text{Years} \\setminus \\{1\\} \\times \\text{Ages} \\setminus \\{1,12\\}\n",
    "\\end{equation}\n",
    "\n",
    "- **Heifers Birth**: Heifers born in year $t$ depend on the number of dairy cows.\n",
    "\n",
    "\\begin{equation}\n",
    "\\text{Newborn}_t + \\text{HF_sell}_t = \\sum_{k \\in \\text{Ages} \\setminus \\{1,12\\}}{\\frac{\\text{Birthrate}}{2}*\\text{Cows}_{t,k}} \\quad \\forall t \\in \\text{Years}\n",
    "\\end{equation}\n",
    "\n",
    "- **Final Dairy Cows**: The number of dairy cows at the end of the planning horizon must be within tolerances.\n",
    "\n",
    "\\begin{equation}\n",
    "\\text{Min_final_cows} \\leq \\sum_{k \\in \\text{Ages} \\setminus \\{1,12\\}}{\\text{Cows}_{5,k}} \\leq \\text{Max_final_cows}\n",
    "\\end{equation}\n",
    "\n",
    "- **Initial Conditions**: Set the number of livestock available at the beginning of the planning horizon.\n",
    "\n",
    "\\begin{equation}\n",
    "\\text{Cows}_{1,1} = \\text{Initial_HF}\n",
    "\\end{equation}\n",
    "\n",
    "\\begin{equation}\n",
    "\\text{Cows}_{1,2} = \\text{Initial_HF}\n",
    "\\end{equation}\n",
    "\n",
    "\\begin{equation}\n",
    "\\text{Cows}_{1,k} = \\text{Initial_cows} \\quad \\forall k \\in \\text{Ages} \\setminus \\{1,2\\}\n",
    "\\end{equation}\n",
    "\n",
    "- **Yearly Profit**: Profit in year $t$ is driven by operations from crops and livestock, after accounting for labor, land and financial costs.\n",
    "\n",
    "\\begin{equation}\n",
    "\\text{Profit}_t = \\frac{\\text{BL_price}*\\text{Birthrate}}{2}*\\sum_{k \\in \\text{Ages} \\setminus \\{1,12\\}}{\\text{Cows}_{t,k}}\n",
    "+ \\text{HF_price}*\\text{HF_sell}_t\n",
    "+ \\text{Cow_price}*\\text{Cows}_{t,12}\n",
    "\\end{equation}\n",
    "\n",
    "\\begin{equation}\n",
    "+ \\text{Milk_price}*\\sum_{k \\in \\text{Ages} \\setminus \\{1,12\\}}{\\text{Cows}_{t,k}}\n",
    "\\end{equation}\n",
    "\n",
    "\\begin{equation}\n",
    "+ \\text{GR_price}*\\text{GR_sell}_t\n",
    "+ \\text{SB_price}*\\text{SB_sell}_t\n",
    "\\end{equation}\n",
    "\n",
    "\\begin{equation}\n",
    "- \\text{GR_cost}*\\text{GR_buy}_t\n",
    "- \\text{SB_cost}*\\text{SB_buy}_t\n",
    "\\end{equation}\n",
    "\n",
    "\\begin{equation}\n",
    "- \\text{Overtime_cost}*\\text{Overtime}_t\n",
    "- \\text{Regular_time_cost}\n",
    "\\end{equation}\n",
    "\n",
    "\\begin{equation}\n",
    "- \\text{HF_cost}*(\\text{Newborn}_t + \\text{Cows}_{t,1})\n",
    "- \\text{Cow_cost}*\\sum_{k \\in \\text{Ages} \\setminus \\{1,12\\}}{\\text{Cows}_{t,k}}\n",
    "\\end{equation}\n",
    "\n",
    "\\begin{equation}\n",
    "- \\text{GR_land_cost}*\\sum_{l \\in \\text{Lands}}{\\frac{\\text{GR}_{t,l}}{\\text{GR_yield}_l}}\n",
    "- \\text{SB_land_cost}*\\frac{\\text{SB}_t}{\\text{SB_yield}} \\\\\n",
    "- \\text{Installment}*\\sum_{d \\in \\text{Years}:d \\leq t}{\\text{Outlay}_d}\n",
    "\\quad \\forall t \\in \\text{Years}\n",
    "\\end{equation}\n",
    "\n",
    "---\n",
    "## Python Implementation\n",
    "\n",
    "We import the Gurobi Python Module and other Python libraries."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%pip install gurobipy"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "import numpy as np\n",
    "import pandas as pd\n",
    "\n",
    "import gurobipy as gp\n",
    "from gurobipy import GRB\n",
    "\n",
    "# tested with Python 3.11 & Gurobi 11.0"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Input Data\n",
    "We define all the input data of the model."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Parameters\n",
    "\n",
    "years = [1,2,3,4,5]\n",
    "lands = [1,2,3,4]\n",
    "ages = [1,2,3,4,5,6,7,8,9,10,11,12]\n",
    "cow_ages = [2,3,4,5,6,7,8,9,10,11]\n",
    "\n",
    "gr_area = {1: 20.0, 2: 30.0, 3: 20.0, 4: 10.0}\n",
    "gr_yield = {1: 1.1,  2: 0.9, 3: 0.8, 4:0.65}\n",
    "sb_yield = 1.5\n",
    "housing_cap = 130\n",
    "gr_intake = 0.6\n",
    "sb_intake = 0.7\n",
    "hf_land = 2/3.0\n",
    "land_cap = 200\n",
    "hf_labor = 10/100.0\n",
    "cow_labor = 42/100.0\n",
    "gr_labor = 4/100.0\n",
    "sb_labor = 14/100.0\n",
    "labor_cap = 5500/100.0\n",
    "cow_decay = 0.02\n",
    "hf_decay = 0.05\n",
    "initial_hf = 9.5\n",
    "initial_cows = 9.8\n",
    "birthrate = 1.1\n",
    "min_final_cows = 50\n",
    "max_final_cows = 175\n",
    "bl_price = 30\n",
    "hf_price = 40\n",
    "cow_price = 120\n",
    "milk_price = 370\n",
    "gr_price = 75\n",
    "sb_price = 58\n",
    "gr_cost = 90\n",
    "sb_cost = 70\n",
    "overtime_cost = 120\n",
    "regular_time_cost = 4000\n",
    "hf_cost = 50\n",
    "cow_cost = 100\n",
    "gr_land_cost = 15\n",
    "sb_land_cost = 10\n",
    "installment = 39.71"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Model Deployment\n",
    "\n",
    "We create a model and the variables. For each, year we have continuous variables, which tell us how much sugar beet is grown (in tons), how much grain is bought (in tons), how much grain is sold (in tons), how much sugar beet is bought (in tons), how much sugar beet is sold (in tons), how much extra labor is recruited, how much capital outlay there is, how many heifers are sold at birth, how much profit there is, and how many cows are newborns (age 0).\n",
    "\n",
    "For each year and each land group, there is a continuous variable, which tells us how much grain is grown on that land group. For each year and each cow age, there is a continuous variable that tells us how many cows exists in the current year of that age."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Using license file c:\\gurobi\\gurobi.lic\n"
     ]
    }
   ],
   "source": [
    "model = gp.Model('Farming')\n",
    "sb = model.addVars(years, vtype=GRB.CONTINUOUS, name=\"SB\")\n",
    "gr_buy = model.addVars(years, vtype=GRB.CONTINUOUS, name=\"GR_buy\")\n",
    "gr_sell = model.addVars(years, vtype=GRB.CONTINUOUS, name=\"GR_sell\")\n",
    "sb_buy = model.addVars(years, vtype=GRB.CONTINUOUS, name=\"SB_buy\")\n",
    "sb_sell = model.addVars(years, vtype=GRB.CONTINUOUS, name=\"SB_sell\")\n",
    "overtime = model.addVars(years, vtype=GRB.CONTINUOUS, name=\"Overtime\")\n",
    "outlay = model.addVars(years, vtype=GRB.CONTINUOUS, name=\"Outlay\")\n",
    "hf_sell = model.addVars(years, vtype=GRB.CONTINUOUS, name=\"HF_sell\")\n",
    "newborn = model.addVars(years, vtype=GRB.CONTINUOUS, name=\"Newborn\")\n",
    "profit = model.addVars(years, vtype=GRB.CONTINUOUS, name=\"Profit\")\n",
    "gr = model.addVars(years, lands, vtype=GRB.CONTINUOUS, name=\"GR\")\n",
    "cows = model.addVars(years, ages, vtype=GRB.CONTINUOUS, name=\"Cows\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Next we insert the constraints:\n",
    "\n",
    "There is only a housing capacity for 130 cows per year. It is possible that there are more than 130 cows, but housing these additional cows will require additional costs related to renting houses, which is covered with the `Outlay` variables."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 1. Housing capacity\n",
    "\n",
    "HousingCap = model.addConstrs((newborn[year] +\n",
    "                    cows[year,1] +\n",
    "                    gp.quicksum(cows[year,age] for age in cow_ages) -\n",
    "                    gp.quicksum(outlay[d] for d in years if d <= year)\n",
    "                    <= housing_cap for year in years), name=\"Housing_cap\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "After selling, buying, and producing grains and sugar beet, there needs to be enough of them in storage to feed all the cows."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 2.1 Food consumption (Grain)\n",
    "\n",
    "GrainConsumption = model.addConstrs((gp.quicksum(gr_intake*cows[year, age] for age in cow_ages)\n",
    "                  <= gr_buy[year] - gr_sell[year] + gr.sum(year, '*')\n",
    "                  for year in years), name=\"Grain_consumption\")\n",
    "\n",
    "# 2.1 Food consumption (Sugar beet)\n",
    "SugarbeetConsumption = model.addConstrs((gp.quicksum(sb_intake*cows[year, age] for age in cow_ages)\n",
    "                  <= sb_buy[year] - sb_sell[year] + sb[year]\n",
    "                  for year in years), name=\"Sugar_beet_consumption\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The grain produced on a land group cannot exceed the specified production capacity of that land group."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 3. Grain growing\n",
    "\n",
    "GrainGrowing = model.addConstrs((gr[year, land] <= gr_yield[land]*gr_area[land]\n",
    "                  for year in years for land in lands), name=\"Grain_growing\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Each cow needs a certain number of acres to support it. The amount depends on the age of the cow. There are 200 acres available at most."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 4. Land capacity\n",
    "\n",
    "LandCap = model.addConstrs((sb[year]/sb_yield + hf_land*(newborn[year] + cows[year,1])\n",
    "                  + gp.quicksum((1/gr_yield[land])*gr[year, land] for land in lands)\n",
    "                  + gp.quicksum(cows[year, age] for age in cow_ages)\n",
    "                  <= land_cap for year in years), name=\"Land_capacity\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Each cow and each acre requires a certain amount of worker time to maintain. The farm is currently able to provide a fixed number of worker hours in a year. Any additional work that needs to be done requires external workers, for which there will be an additional cost."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 5. Labor\n",
    "\n",
    "Labor = model.addConstrs((hf_labor*(newborn[year] + cows[year,1])\n",
    "                  + gp.quicksum(cow_labor*cows[year, age] for age in cow_ages)\n",
    "                  + gp.quicksum(gr_labor/gr_yield[land]*gr[year,land] for land in lands)\n",
    "                  + sb_labor/sb_yield*sb[year] \n",
    "                  <= labor_cap + overtime[year] for year in years), name=\"Labor\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Each year a certain percentage of the cows die, depending on their age."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 6.1 Continuity\n",
    "\n",
    "Continuity1 = model.addConstrs((cows[year,1] == (1-hf_decay)*newborn[year-1] \n",
    "                  for year in years if year > min(years)),\n",
    "                 name=\"Continuity_a\")\n",
    "\n",
    "# 6.2 Continuity\n",
    "\n",
    "Continuity2 = model.addConstrs((cows[year,2] == (1-hf_decay)*cows[year-1,1] \n",
    "                  for year in years if year > min(years)),\n",
    "                 name=\"Continuity_b\")\n",
    "\n",
    "# 6.3 Continuity\n",
    "\n",
    "Continuity3 = model.addConstrs((cows[year,age+1] == (1-cow_decay)*cows[year-1,age] \n",
    "                  for year in years for age in cow_ages if year > min(years)),\n",
    "                 name=\"Continuity_c\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Keep track of the number of cows; cows can come into/out of the model by being bought or sold or through birth."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 7. Heifers birth\n",
    "\n",
    "HeifersBirth = model.addConstrs((newborn[year] + hf_sell[year] \n",
    "                  == gp.quicksum(birthrate/2*cows[year,age] for age in cow_ages) for year in years)\n",
    "                 , name=\"Heifers_birth\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "At the end of the five years, the farmer wants at least 50 and at most 175 diary cows."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 8. Final dairy cows\n",
    "FinalDairyCows = model.addRange(gp.quicksum(cows[max(years), age] for age in cow_ages), min_final_cows, max_final_cows, name=\"Final_dairy_cows\" )"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "In the first year, there are 9.5 one-year-old cows and 9.5 two-year-old cows. In addition, there are 9.8 cows for each age from three to 12. Note that we are solving this as an LP model to make it easier to solve. This can lead to fractional values for variables, which are in reality integers. "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 9.1-9.2 Initial conditions\n",
    "\n",
    "InitialHeifers = model.addConstrs((initial_hf == cows[1, age] for age in ages if age < 3),\n",
    "                 name=\"Initial_conditions\")\n",
    "\n",
    "# 9.3 Initial conditions\n",
    "\n",
    "InitialCows = model.addConstrs((initial_cows == cows[1, age] for age in ages if age >= 3),\n",
    "                 name=\"Initial_condition_cows\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The following constraints determine yearly profits. The costs for labor currently total $\\$4,000$. The profit is influenced by the selling of bullocks and heifers, selling of 12-year-old-cows, selling of milk, selling of grain, selling of sugar beet, buying of grain, buying of sugar beet, labor costs, heifer costs, dairy cow costs, grain costs, sugar beet costs, and capital costs."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 10. Yearly profit\n",
    "\n",
    "YearlyProfit = model.addConstrs((profit[year]\n",
    "                  == bl_price*birthrate/2*gp.quicksum(cows[year, age] for age in cow_ages)\n",
    "                  + hf_price*hf_sell[year] + cow_price*cows[year, 12]\n",
    "                  + milk_price*gp.quicksum(cows[year, age] for age in cow_ages)\n",
    "                  + gr_price*gr_sell[year] + sb_price*sb_sell[year]\n",
    "                  - gr_cost*gr_buy[year] - sb_cost*sb_buy[year]\n",
    "                  - overtime_cost*overtime[year] - regular_time_cost\n",
    "                  - hf_cost*(newborn[year] + cows[year,1])\n",
    "                  - cow_cost*gp.quicksum(cows[year, age] for age in cow_ages)\n",
    "                  - gr_land_cost*gp.quicksum(gr[year, land]/gr_yield[land] for land in lands)\n",
    "                  - sb_land_cost*sb[year]/sb_yield\n",
    "                  - installment*gp.quicksum(outlay[d] for d in years if d <= year)\n",
    "                  for year in years), name=\"Yearly_profit\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The total profit of the planning horizon consists of the calculated profits minus the loan payments that remain pending:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 0. Total profit\n",
    "\n",
    "model.setObjective(gp.quicksum(profit[year] - installment*(year+4)*outlay[year] for year in years), GRB.MAXIMIZE)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Next, we start the optimization and Gurobi finds the optimal solution."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Gurobi Optimizer version 9.1.0 build v9.1.0rc0 (win64)\n",
      "Thread count: 4 physical cores, 8 logical processors, using up to 8 threads\n",
      "Optimize a model with 116 rows, 131 columns and 734 nonzeros\n",
      "Model fingerprint: 0x1612a027\n",
      "Coefficient statistics:\n",
      "  Matrix range     [4e-02, 3e+02]\n",
      "  Objective range  [1e+00, 4e+02]\n",
      "  Bounds range     [1e+02, 1e+02]\n",
      "  RHS range        [7e+00, 4e+03]\n",
      "Presolve removed 84 rows and 67 columns\n",
      "Presolve time: 0.01s\n",
      "Presolved: 32 rows, 64 columns, 252 nonzeros\n",
      "\n",
      "Iteration    Objective       Primal Inf.    Dual Inf.      Time\n",
      "       0    5.1200000e+32   5.000000e+30   5.120000e+02      0s\n",
      "      24    1.2171917e+05   0.000000e+00   0.000000e+00      0s\n",
      "\n",
      "Solved in 24 iterations and 0.01 seconds\n",
      "Optimal objective  1.217191729e+05\n"
     ]
    }
   ],
   "source": [
    "model.optimize()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "---\n",
    "## Analysis\n",
    "\n",
    "The optimal plan results in a total profit of $\\$121,719.17$ over the five-year period the model covers. The detailed plan for each year is as follows.\n",
    "\n",
    "### Financial Plan\n",
    "\n",
    "This plan determines the profit and outlay at each period of the planning horizon. For example, the profit in year 1 is $\\$21,906.1$ and the outlay is zero dollars."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>1</th>\n",
       "      <th>2</th>\n",
       "      <th>3</th>\n",
       "      <th>4</th>\n",
       "      <th>5</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>Profit</th>\n",
       "      <td>21906.1</td>\n",
       "      <td>21888.7</td>\n",
       "      <td>25816.1</td>\n",
       "      <td>26825.8</td>\n",
       "      <td>25282.6</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>Outlay</th>\n",
       "      <td>0.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.0</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "              1        2        3        4        5\n",
       "Profit  21906.1  21888.7  25816.1  26825.8  25282.6\n",
       "Outlay      0.0      0.0      0.0      0.0      0.0"
      ]
     },
     "execution_count": 16,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "rows = [\"Profit\", \"Outlay\"]\n",
    "columns = years.copy()\n",
    "finance_plan = pd.DataFrame(columns=columns, index=rows, data=0.0)\n",
    "\n",
    "for year in years:\n",
    "    if (abs(profit[year].x) > 1e-6):\n",
    "        finance_plan.loc[\"Profit\", year] = np.round(profit[year].x, 1)\n",
    "    if (abs(outlay[year].x) > 1e-6):\n",
    "        finance_plan.loc[\"Outlay\", year] = np.round(outlay[year].x, 1)\n",
    "finance_plan"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Plan for Grains\n",
    "This plan defines the number of tons of grain to grow for each type of land group (rows) at each year of the planning horizon (columns). It also defines the number of tons of grain to buy and sell at each year of the planning horizon. For example, we are going to grow 22 tons of grain at land group 1 during year 2 . In addition, we are going to buy 35.1 tons of grain during year 2."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>1</th>\n",
       "      <th>2</th>\n",
       "      <th>3</th>\n",
       "      <th>4</th>\n",
       "      <th>5</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>22.0</td>\n",
       "      <td>22.0</td>\n",
       "      <td>22.0</td>\n",
       "      <td>22.0</td>\n",
       "      <td>22.0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>0.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>2.8</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>0.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>0.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>Buy</th>\n",
       "      <td>36.6</td>\n",
       "      <td>35.1</td>\n",
       "      <td>37.8</td>\n",
       "      <td>40.1</td>\n",
       "      <td>33.5</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>Sell</th>\n",
       "      <td>0.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.0</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "         1     2     3     4     5\n",
       "1     22.0  22.0  22.0  22.0  22.0\n",
       "2      0.0   0.0   2.8   0.0   0.0\n",
       "3      0.0   0.0   0.0   0.0   0.0\n",
       "4      0.0   0.0   0.0   0.0   0.0\n",
       "Buy   36.6  35.1  37.8  40.1  33.5\n",
       "Sell   0.0   0.0   0.0   0.0   0.0"
      ]
     },
     "execution_count": 17,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "rows = lands.copy() + [\"Buy\", \"Sell\"]\n",
    "columns = years.copy()\n",
    "gr_plan = pd.DataFrame(columns=columns, index=rows, data=0.0)\n",
    "\n",
    "for year, land in gr.keys():\n",
    "    if (abs(gr[year, land].x) > 1e-6):\n",
    "        gr_plan.loc[land, year] = np.round(gr[year, land].x, 1)\n",
    "for year in years:\n",
    "    if (abs(gr_buy[year].x) > 1e-6):\n",
    "        gr_plan.loc[\"Buy\", year] = np.round(gr_buy[year].x, 1)\n",
    "    if (abs(gr_sell[year].x) > 1e-6):\n",
    "        gr_plan.loc[\"Sell\", year] = np.round(gr_sell[year].x, 1)\n",
    "gr_plan"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Plan for Sugar Beet\n",
    "This plan defines the number of tons of sugar beet to grow at each year of the planning horizon (columns). It also defines the number of tons of sugar beet to buy and sell at each year of the planning horizon. For example, we are going to grow 94 tons of sugar beet during year 2 . In addition, we are going to sell 27.4 tons of sugar beet during year 2."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>1</th>\n",
       "      <th>2</th>\n",
       "      <th>3</th>\n",
       "      <th>4</th>\n",
       "      <th>5</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>Grow</th>\n",
       "      <td>91.1</td>\n",
       "      <td>94.0</td>\n",
       "      <td>97.7</td>\n",
       "      <td>114.6</td>\n",
       "      <td>131.3</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>Buy</th>\n",
       "      <td>0.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>Sell</th>\n",
       "      <td>22.8</td>\n",
       "      <td>27.4</td>\n",
       "      <td>24.6</td>\n",
       "      <td>42.1</td>\n",
       "      <td>66.6</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "         1     2     3      4      5\n",
       "Grow  91.1  94.0  97.7  114.6  131.3\n",
       "Buy    0.0   0.0   0.0    0.0    0.0\n",
       "Sell  22.8  27.4  24.6   42.1   66.6"
      ]
     },
     "execution_count": 18,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "rows = [\"Grow\", \"Buy\", \"Sell\"]\n",
    "columns = years.copy()\n",
    "sb_plan = pd.DataFrame(columns=columns, index=rows, data=0.0)\n",
    "\n",
    "for year in years:\n",
    "    if (abs(sb[year].x) > 1e-6):\n",
    "        sb_plan.loc[\"Grow\", year] = np.round(sb[year].x, 1)\n",
    "    if (abs(sb_buy[year].x) > 1e-6):\n",
    "        sb_plan.loc[\"Buy\", year] = np.round(sb_buy[year].x, 1)\n",
    "    if (abs(sb_sell[year].x) > 1e-6):\n",
    "        sb_plan.loc[\"Sell\", year] = np.round(sb_sell[year].x, 1)\n",
    "sb_plan"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Plan for Heifers\n",
    "\n",
    "This plan shows number of heifers to sell and raise at each period of the planning horizon. For example, we are going to sell 40.8 heifers and raise 11.6 heifers during year 2."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>1</th>\n",
       "      <th>2</th>\n",
       "      <th>3</th>\n",
       "      <th>4</th>\n",
       "      <th>5</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>Sell</th>\n",
       "      <td>30.9</td>\n",
       "      <td>40.8</td>\n",
       "      <td>57.4</td>\n",
       "      <td>57.0</td>\n",
       "      <td>50.9</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>Raise</th>\n",
       "      <td>22.8</td>\n",
       "      <td>11.6</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.0</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "          1     2     3     4     5\n",
       "Sell   30.9  40.8  57.4  57.0  50.9\n",
       "Raise  22.8  11.6   0.0   0.0   0.0"
      ]
     },
     "execution_count": 19,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "rows = [\"Sell\", \"Raise\"]\n",
    "columns = years.copy()\n",
    "livestock_plan = pd.DataFrame(columns=columns, index=rows, data=0.0)\n",
    "\n",
    "for year in years:\n",
    "    if (abs(hf_sell[year].x) > 1e-6):\n",
    "        livestock_plan.loc[\"Sell\", year] = np.round(hf_sell[year].x, 1)\n",
    "    if (abs(newborn[year].x) > 1e-6):\n",
    "        livestock_plan.loc[\"Raise\", year] = np.round(newborn[year].x, 1)\n",
    "livestock_plan"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "---\n",
    "## References\n",
    "\n",
    "H. Paul Williams, Model Building in Mathematical Programming, fifth edition.\n",
    "\n",
    "Copyright © 2020 Gurobi Optimization, LLC"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.1"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
